/*
 * Dcm_UDS0x36.c
 *
 *  Created on: 2018-8-21
 *      Author: tao.yu
 */

#include "UDS.h"


/****************************************************************
     UDS: TransferData (36 hex) service
 ***************************************************************/
#if (STD_ON == DCM_UDS_SERVICE0X36_ENABLED)

/***************************/
#define DCM_START_SEC_CODE
#include "Dcm_MemMap.h"
static FUNC(Std_ReturnType, DCM_CODE)Dcm_Uds0x36ServiceConditionCheck(
        uint8 ProtocolCtrlId,
        uint8 MsgCtrlId)
{
    Std_ReturnType ret = E_OK;

    /*************************************************/
#if(STD_ON == DCM_SESSION_FUNC_ENABLED)
    /*session check,check whether the current
     * session supports the request service*/
    ret = DsdInternal_SesCheck(ProtocolCtrlId,
            SID_TRANSFER_DATA);
    if(E_NOT_OK == ret)
    {
        /****@req DCM-FUNR-073[DCM211]****/
        /*the current session does not support
         * the request service,send NRC = 0x7F*/
        (void)DsdInternal_SetNrc(ProtocolCtrlId,
                DCM_E_SERVICENOTSUPPORTEDINACTIVESESSION);
        DsdInternal_ProcessingDone(ProtocolCtrlId);
        return E_NOT_OK;
    }
#endif

    /*************************************************/
#if(STD_ON == DCM_SECURITY_FUNC_ENABLED)
    /*security check,check whether the
     * current security supports the request service*/
    ret = DsdInternal_SecurityCheck(ProtocolCtrlId,
            SID_TRANSFER_DATA);
    if(E_NOT_OK == ret)
    {
        /****@req DCM-FUNR-074[DCM217]****/
        /*the current security does not support
         * the request service,send NRC = 0x33*/
        (void)DsdInternal_SetNrc(ProtocolCtrlId,
                DCM_E_SECURITYACCESSDENIED);
        DsdInternal_ProcessingDone(ProtocolCtrlId);
        return E_NOT_OK;
    }
#endif
    /*min-length check*/
    if (Dcm_DspProgram.Status == DCM_UDS0X36_TO_UPLOAD)
    {
        if (DCM_UDS0X36_REQ_DATA_UPLOAD_MINLENGTH
                > Dcm_MsgCtrl[MsgCtrlId].MsgContext.ReqDataLen)
        {
            /*the min length of message is not correct,send NRC 0x13*/
            (void)DsdInternal_SetNrc(ProtocolCtrlId,
                    DCM_E_INCORRECTMESSAGELENGTHORINVALIDFORMAT);
            DsdInternal_ProcessingDone(ProtocolCtrlId);
            return E_NOT_OK;
        }
    }
    else if (Dcm_DspProgram.Status == DCM_UDS0X36_TO_DOWNLOAD)
    {
        if (DCM_UDS0X36_REQ_DATA_DOWNLOAD_MINLENGTH
                > Dcm_MsgCtrl[MsgCtrlId].MsgContext.ReqDataLen)
        {
            /*the min length of message is not correct,send NRC 0x13*/
            (void)DsdInternal_SetNrc(ProtocolCtrlId,
                    DCM_E_INCORRECTMESSAGELENGTHORINVALIDFORMAT);
            DsdInternal_ProcessingDone(ProtocolCtrlId);
            return E_NOT_OK;
        }
    }
    else
    {
        /*the request message is not sequence,send NRC 0x22*/
        (void)DsdInternal_SetNrc(ProtocolCtrlId, DCM_E_CONDITIONSNOTCORRECT);
        DsdInternal_ProcessingDone(ProtocolCtrlId);
        return E_NOT_OK;
    }
    return ret;
}
#define DCM_STOP_SEC_CODE
#include "Dcm_MemMap.h"


/*******************************/
#define DCM_START_SEC_CODE
#include "Dcm_MemMap.h"
FUNC(Std_ReturnType, DCM_CODE)Dcm_UDS0x36(
        Dcm_OpStatusType OpStatus,
        uint8  ProtocolCtrlId,
        P2VAR(Dcm_NegativeResponseCodeType,AUTOMATIC,DCM_VAR) ErrorCode)
{
    uint8  MsgCtrlId = 0u;
    Std_ReturnType ret = E_OK;
    uint8  TxChannelCtrlIndex = 0u;
    uint8  TxChannelCfgIndex = 0u;
    uint16 Offset = 0u;
    uint8  DataBlockId = 0;
    uint8 MemoryIdentifier = 0;
    uint8* DCM_MemoryData;

    /*************************************************/
    /*if the required protocol is configured,get the index of runtime datum*/
    MsgCtrlId =  Dcm_ProtocolCtrl[ProtocolCtrlId].MsgCtrlIndex;

    /*************************************************/
    ret = Dcm_Uds0x36ServiceConditionCheck(ProtocolCtrlId, MsgCtrlId);
    if(E_OK != ret)
    {
        return ret;
    }

    if ((Dcm_DspProgram.Status == DCM_UDS0X36_TO_UPLOAD)
            || (Dcm_DspProgram.Status == DCM_UDS0X36_TO_DOWNLOAD))
    {
        if (Dcm_DspProgram.MemoryIdInfoIndex != 0xFFu)
        {
            MemoryIdentifier = Dcm_DspCfg.pDcmDspMemory->
               DcmDspMemoryIdInfo[Dcm_DspProgram.MemoryIdInfoIndex].
               DcmDspMemoryIdValue;
        }
        else
        {
            /*the MemoryIdInfoIndex is not correct,send NRC 0x22*/
            (void)DsdInternal_SetNrc(ProtocolCtrlId,
                    DCM_E_CONDITIONSNOTCORRECT);
            DsdInternal_ProcessingDone(ProtocolCtrlId);
            return E_NOT_OK;
        }
    }

    DataBlockId = Dcm_MsgCtrl[MsgCtrlId].MsgContext.pReqData[1];
    /* then calculate block index and check block index*/
    if ((uint8)0xFFU == Dcm_DspProgram.blockId)
    {
        Dcm_DspProgram.blockId = (uint8)0;
    }
    else
    {
        Dcm_DspProgram.blockId++;
    }

    if (Dcm_DspProgram.blockId != DataBlockId)
    {
        /* program block index is not correct,
         * send nrc 0x73 [SWS_Dcm_00645]*/
        (void)DsdInternal_SetNrc(ProtocolCtrlId,
                DCM_E_WRONGBLOCKSEQUENCECOUNTER);
        DsdInternal_ProcessingDone(ProtocolCtrlId);
        return E_NOT_OK;
    }


    TxChannelCtrlIndex = Dcm_MsgCtrl[MsgCtrlId].Dcm_TxCtrlChannelIndex;
    TxChannelCfgIndex  = Dcm_ChannelCtrl[TxChannelCtrlIndex].Dcm_ChannelCfgIndex;
    Offset = (Dcm_DslCfg.pDcmChannelCfg)[TxChannelCfgIndex].offset;

    /*process is running and the request format is correct,to call the callout
     * Following NRCs shall be the responsibility of the callout function
     * [SWS_Dcm_01173] 0x23,0x31,0x71,0x72,0x92,0x93*/
    if ((Dcm_DspProgram.Status == DCM_UDS0X36_TO_UPLOAD)
            || (Dcm_DspProgram.Status == DCM_UDS0X38_0x04)
            || (Dcm_DspProgram.Status == DCM_UDS0X38_0x05))
    {
        DCM_MemoryData = &Dcm_Channel[Offset + 2u];
        /*[SWS_Dcm_00504] */
        ret = Dcm_ReadMemory(OpStatus,
                                MemoryIdentifier,
                                Dcm_DspProgram.address,
                                Dcm_DspProgram.BlockLength,
                                DCM_MemoryData,
                                ErrorCode);
        if (DCM_READ_FAILED == ret)
        {
            /*the processing is not successful,send NRC */
            (void)DsdInternal_SetNrc(ProtocolCtrlId, *ErrorCode);
            DsdInternal_ProcessingDone(ProtocolCtrlId);
            return E_NOT_OK;
        }
        else if(DCM_READ_FORCE_RCRRP == ret)
        {
            /*the processing is pending,send NRC 0x78[SWS_Dcm_00839][SWS_Dcm_00840] */
            (void)DsdInternal_SetNrc(ProtocolCtrlId, DCM_E_RESPONSE_PENDING);
            DsdInternal_ProcessingDone(ProtocolCtrlId);
            Dcm_MsgCtrl[MsgCtrlId].Dcm_Ret = DCM_E_FORCE_RCRRP;
            return DCM_E_PENDING;
        }
        else if (DCM_READ_PENDING == ret)
        {
            Dcm_MsgCtrl[MsgCtrlId].Dcm_OpStatus = DCM_PENDING;
            return ret;
        }
        else
        {
            /*idle*/
        }
    }
    else if ((Dcm_DspProgram.Status == DCM_UDS0X36_TO_DOWNLOAD)
            || (Dcm_DspProgram.Status == DCM_UDS0X38_0x01)
            || (Dcm_DspProgram.Status == DCM_UDS0X38_0x03))
    {
        DCM_MemoryData = &(Dcm_MsgCtrl[MsgCtrlId].MsgContext.pReqData[2u]);
        if (Dcm_DspProgram.BlockLength
                != (Dcm_MsgCtrl[MsgCtrlId].MsgContext.ReqDataLen - 2u))
        {
            /*the request message length is not correct,send NRC 0x22*/
            (void)DsdInternal_SetNrc(ProtocolCtrlId, DCM_E_CONDITIONSNOTCORRECT);
            DsdInternal_ProcessingDone(ProtocolCtrlId);
            return E_NOT_OK;
        }
        /*[SWS_Dcm_00503] */
        ret = Dcm_WriteMemory(OpStatus,
                                MemoryIdentifier,
                                Dcm_DspProgram.address,
                                Dcm_DspProgram.BlockLength,
                                DCM_MemoryData,
                                ErrorCode);

        if (DCM_WRITE_FAILED == ret)
        {
            /*the processing is not successful,send NRC [SWS_Dcm_00643]*/
            (void)DsdInternal_SetNrc(ProtocolCtrlId, *ErrorCode);
            DsdInternal_ProcessingDone(ProtocolCtrlId);
            return E_NOT_OK;
        }
        else if(DCM_WRITE_FORCE_RCRRP == ret)
        {
            /*the processing is pending,send NRC 0x78[SWS_Dcm_00837][SWS_Dcm_00838] */
            (void)DsdInternal_SetNrc(ProtocolCtrlId, DCM_E_RESPONSE_PENDING);
            DsdInternal_ProcessingDone(ProtocolCtrlId);
            Dcm_MsgCtrl[MsgCtrlId].Dcm_Ret = DCM_E_FORCE_RCRRP;
            return DCM_E_PENDING;
        }
        else if (DCM_WRITE_PENDING == ret)
        {
            Dcm_MsgCtrl[MsgCtrlId].Dcm_OpStatus = DCM_PENDING;
            return ret;
        }
        else
        {
            /*idle*/
        }
    }
    else
    {
        (void)DsdInternal_SetNrc(ProtocolCtrlId,DCM_E_CONDITIONSNOTCORRECT);
        DsdInternal_ProcessingDone(ProtocolCtrlId);
        return E_NOT_OK;
    }

    /* check tx data length */
    if (Dcm_DspProgram.Status == DCM_UDS0X36_TO_UPLOAD)
    {
        if ((2u + Dcm_DspProgram.BlockLength)
                > (Dcm_DslCfg.pDcmChannelCfg[TxChannelCfgIndex].Dcm_DslBufferSize))
        {
            /*Pdu length is bigger than buffer size */
            (void)DsdInternal_SetNrc(ProtocolCtrlId,DCM_E_RESPONSETOOLONG);
            DsdInternal_ProcessingDone(ProtocolCtrlId);
            return E_NOT_OK;
        }
    }
    else
    {
        if ((2u) > (Dcm_DslCfg.pDcmChannelCfg[TxChannelCfgIndex].Dcm_DslBufferSize))
        {
            /*Pdu length is bigger than buffer size */
            (void)DsdInternal_SetNrc(ProtocolCtrlId,DCM_E_RESPONSETOOLONG);
            DsdInternal_ProcessingDone(ProtocolCtrlId);
            return E_NOT_OK;
        }
    }

    if ((Dcm_DspProgram.Status == DCM_UDS0X36_TO_UPLOAD)
            || (Dcm_DspProgram.Status == DCM_UDS0X36_TO_DOWNLOAD))
    {
        /* calculate address */
        Dcm_DspProgram.address += Dcm_DspProgram.BlockLength;
    }

    /**********************************************************
     * assemble positive response
     *********************************************************/
    /*the processing is successful,assemble positive response*/
    SchM_Enter_Dcm(Dcm_Channel);
    Dcm_Channel[Offset] = 0x76;             /*response SID*/
    Dcm_Channel[Offset + 1u] = Dcm_DspProgram.blockId;
    /*blockSequenceCounter*/
    SchM_Exit_Dcm(Dcm_Channel);
    SchM_Enter_Dcm(Dcm_MsgCtrl);
    if ((Dcm_DspProgram.Status == DCM_UDS0X36_TO_UPLOAD)
            || (Dcm_DspProgram.Status == DCM_UDS0X38_0x04)
            || (Dcm_DspProgram.Status == DCM_UDS0X38_0x05))
    {
        Dcm_MsgCtrl[MsgCtrlId].MsgContext.ResMaxDataLen =
                2u + Dcm_DspProgram.BlockLength;
        Dcm_MsgCtrl[MsgCtrlId].MsgContext.ResDataLen    =
                2u + Dcm_DspProgram.BlockLength;
    }
    else if ((Dcm_DspProgram.Status == DCM_UDS0X36_TO_DOWNLOAD)
            || (Dcm_DspProgram.Status == DCM_UDS0X38_0x01)
            || (Dcm_DspProgram.Status == DCM_UDS0X38_0x03))
    {
        Dcm_MsgCtrl[MsgCtrlId].MsgContext.ResMaxDataLen = 2u;
        Dcm_MsgCtrl[MsgCtrlId].MsgContext.ResDataLen    = 2u;
    }
    else
    {
        /*idle*/
    }
    Dcm_MsgCtrl[MsgCtrlId].MsgContext.pResData      = &Dcm_Channel[Offset];
    SchM_Exit_Dcm(Dcm_MsgCtrl);
    DsdInternal_ProcessingDone(ProtocolCtrlId);

    return ret;
}
#define DCM_STOP_SEC_CODE
#include "Dcm_MemMap.h"

#endif

